﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using MySql.Data.MySqlClient;
namespace Region
{
    /// <summary>
    /// Otdel - клас описывает доступ к таблице mysql:rpn.otdel
    /// </summary>
    [DBObject(Table = "otdel", PrimaryKeyPole = "OtdelID")]
    public class Otdel: DBObject
    {      
      #region Поля 
      [DBColumn]
      public Int32 OtdelID { get; set; }
      public Int32 OID {
      	get
      	{
      		if (TO==1) return OtdelID;
      		for(Otdel O = ParentOtdel;O!=null;O=O.ParentOtdel)
      			if (O.TO==1) 
      				return O.OtdelID;
      		return 0;
      	}
      }
      [DBColumn]
      public Int32 ParentOtdelID { get; set; }
      [DBColumn]
      public Int32 TO { get; set; }
      [DBColumn]
      public Int32 Level { get; set; }
      [DBColumn]
      public String OtdelName { get; set; }
      [DBColumn]
      public String OtdelInfo { get; set; }
      [DBColumn]
      public String OtdelInfo2 { get; set; }

      public Otdel ParentOtdel { get{return m_engine.getOtdel(ParentOtdelID);}set{ParentOtdelID = value.ParentOtdelID;}}
      #endregion
      public Otdel(Engine engine,Int32 OtdelID):base(engine, OtdelID)
      {

      }
      public bool isSubOtdel(int OtdelID) { return m_engine.getOtdel(OtdelID).ParentOtdelID==OtdelID; }
      public override bool poleAccess(String PoleName)
      {
        // FIXME Приданной реализации никто не сможет изменить справочник отделы
        return false;
      }
      #region Члены ITreeValue
      public object ItemID{get { return OtdelID; }}
      public object ItemParentID{get { return ParentOtdelID; }}
      public String ItemCaption{get { return OtdelName; }}
      #endregion
    }
  public struct OtdelListLine
  {
    public Int32 OtdelID;
    public Int32 ParentOtdelID;
    public String OtdelName;
  }
  public class OtdelList:DBList<OtdelListLine>
  {
    public OtdelList(Engine engine):base(engine)
    {
      DefaultPoles.Add("otdel.OtdelID");
      DefaultPoles.Add("otdel.ParentOtdelID");
      DefaultPoles.Add("otdel.OtdelName");
      DefaultTables.Add("otdel");
      DefaultOrderBy.Add("otdel.OtdelName ASC");    
    }
    protected override void ProceessWheres(SQLParam Params,List<String> Tables, List<String> Poles,List<String> Wheres,List<String> OrderBy)
    {
      Int32 ParentOtdelID;
      Boolean TO,Root;
      if (m_wheres.ContainsKey("ParentOtdelID") && (int)m_wheres["ParentOtdelID"]>0 && Int32.TryParse(m_wheres["ParentOtdelID"].ToString(), out ParentOtdelID))
      {
        Tables.Add("INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=otdel.OtdelID");
        Wheres.Add("otdel_otdel.ParentOtdelID=@ParentOtdelID");
        Params["@ParentOtdelID"] = ParentOtdelID;        
      }
      if (m_wheres.ContainsKey("TO") && Boolean.TryParse(m_wheres["TO"].ToString(), out TO) )
      {
        Tables.Add("INNER JOIN otdel_value ON otdel_value.OtdelID=otdel.OtdelID");
        Wheres.Add("otdel_value.ID=1");// выбрать только Территориальные отделы 
        if (TO)
          Wheres.Add("otdel_value.OtdelID=otdel_value.Value");
        else
          Wheres.Add("otdel_value.OtdelID<>otdel_value.Value");
      }
      if (m_wheres.ContainsKey("Root") && Boolean.TryParse(m_wheres["Root"].ToString(), out Root) )
      {
        Tables.Add("LEFT JOIN otdel as protdel ON protdel.OtdelID=otdel.ParentOtdelID");
        if (Root)
          Wheres.Add("protdel.OtdelID Is Null");
        else
          Wheres.Add("protdel.OtdelID Is not Null");
      }
    }
    protected override OtdelListLine readLine(Dictionary<String, Object> r)
    {
      var l = new OtdelListLine();
      l.OtdelID = (Int32)r["OtdelID"];
      l.ParentOtdelID = (Int32)r["ParentOtdelID"];
      l.OtdelName = (String)r["OtdelName"];
      return l;
    }
  };
    public partial class Engine
    {       
        /// <summary> Максимальная глубина отделов</summary>
        const Int32 MaxOtdelDepth = 10;
        /// <summary> Нормализирует данные об отделах после изменения структуры отделов </summary>
        public void NormalizeOtdels()
        {
            SQLEdit("UPDATE otdel SET Level=0");
            for (Int32 i = 0; i < MaxOtdelDepth; i++ )
                SQLEdit("UPDATE `otdel` INNER JOIN `otdel` AS `po` ON `po`.`OtdelID` = `otdel`.`ParentOtdelID` SET `otdel`.`Level` = `po`.`Level`+1 WHERE `otdel`.`Level` <> `po`.`Level`+1");
            SQLEdit("TRUNCATE TABLE `otdel_otdel`");
            SQLEdit("INSERT INTO `otdel_otdel`(`ParentOtdelID`,`OtdelID`) SELECT `ParentOtdelID`, `OtdelID` FROM `otdel` WHERE 1");
            for (Int32 i = 0; i < MaxOtdelDepth; i++)
                SQLEdit(@"INSERT IGNORE INTO  `otdel_otdel`(`ParentOtdelID`,`OtdelID`) SELECT `otdel_otdel`.`ParentOtdelID`, `otdel`.`OtdelID` FROM `otdel` INNER JOIN `otdel_otdel` ON `otdel_otdel`.`OtdelID` = `otdel`.`ParentOtdelID`");             
        }
        private Dictionary<Int32, Otdel> l_Otdel;
        ///<summary> Получить отдел по его идентификатору</summary>
        public Otdel getOtdel(Int32 OtdelID)
        {
          if (l_Otdel == null) l_Otdel = Otdels;          
          if (l_Otdel.ContainsKey(OtdelID)) return (Otdel)l_Otdel[OtdelID];
          if (OtdelID==0) return null;
          Otdel otdel = new Otdel(this, OtdelID);
          l_Otdel[OtdelID] = otdel;
          return otdel;
        }        
        ///<summary> Список всех отделов</summary>
        public Dictionary<Int32, Otdel> Otdels
        {
            get
            {
                if (l_Otdel == null) 
                {
                  l_Otdel = new Dictionary<Int32, Otdel>();
                  SQLResult r = SQLSelect("SELECT * FROM otdel WHERE 1");
                  for (Int32 i = 0; i < r.Count; i++)
                  {
                    Otdel O = new Otdel(this,(Int32)r[i]["OtdelID"]);
                    O.read(r[i]);
                    l_Otdel[(Int32)r[i]["OtdelID"]] = O;
                  }                  
                }
                return new Dictionary<Int32, Otdel>(l_Otdel);
            }
        }

        
        public Dictionary<Int32, Object> OtdelsForTree
        {
            get
            {
                Dictionary<Int32, Object> r = new Dictionary<Int32, Object>();
                foreach (var i in Otdels) r.Add(i.Key, i.Value);                
                return r;
            }
        }      
        public Dictionary<Int32, Object> OIDForTree
        {
            get
            {
                Dictionary<Int32, Object> r = new Dictionary<Int32, Object>();
                foreach (var i in Otdels) 
                	if (i.Value.TO==1) 
                		r.Add(i.Key, i.Value);
                return r;
            }
        } 
    }
}

